import fs from 'fs';
import { tools } from './tools/tools';
import { res_format } from './res_format';
// import { format_genrator } from './format_genrator';

export { cfg_genrator };

namespace cfg_genrator {

	type RESOURCE_TYPE = {
		groups: tools.GROUP_TYPE[],
		resources: tools.RES_TYPE[]
	};

	const TMPLATE: tools.GENRATOR_CFG_TYPE = {
		name: "default",
		res_path: "resource",
		include: [],
		exclude: [],
		group_cfg: "group_cfg_",
		outputdir: ""
	}

	export class CfgGenRator {
		constructor(root: string, genReport: boolean) {

			this.curRoot = root;
			this.generalCfg = tools.GenricCfg();

			// this.formater = new format_genrator.CfgFormat();
			this.formater = new res_format.ResCheck(root).BuildTree();

			tools.CreateFolder(this.CfgPath);
			let imgPath = `${this.CfgPath}/${this.generalCfg.img_cfg_file}`;
			if (!fs.existsSync(imgPath)) { //不存在拷贝一份
				fs.copyFileSync(tools.TMP_IMG_PATH, imgPath);
			}


			tools.GlobFile(['*.json'], '', {
				nodir: true,
				cwd: this.ResPath
			}).then(matches => {
				this.CfgLoader(matches, genReport);
			});
		}

		private async CfgLoader(rescfg: string[], genReport: boolean) {
			let cfgFile: tools.GENRATOR_CFG_TYPE[] = [];

			let extFiles = tools.QueryEgretProperties(this.curRoot)?.resource_gen?.exclude_cfg_file || [];
			for (let resPath of rescfg) {
				if (extFiles.indexOf(resPath) >= 0) {
					console.log(`due to general.json, ${resPath} will be skiped`);
					continue;
				}
				let cfg = await this.CfgAnalyzer(resPath);
				if (!cfg) {
					continue;
				}
				let formatedData = this.formater.CheckFiles(cfg.include || [], false); //这里是膨胀之后的数据

				genReport && fs.writeFileSync(`${this.CfgPath}/report.${cfg.name}`, JSON.stringify(this.formater.GenFolderReport(), null, 4), {
					encoding: 'utf-8'
				});

				cfg.include = formatedData.include;
				cfg.exclude = formatedData.exclude;
				!!cfg && cfgFile.push(cfg);
			}

			fs.writeFileSync(`${this.CfgPath}/${this.generalCfg.cfg_file}`, JSON.stringify(cfgFile, null, 4), {
				encoding: 'utf-8'
			});
		}

		/**
		 * 生成的数据会做膨胀(sheet和font文件在排除是时需要把png文件压进去)
		 * @param path
		 * @returns
		 */
		private async CfgAnalyzer(path: string): Promise<tools.GENRATOR_CFG_TYPE | null> {
			return new Promise<tools.GENRATOR_CFG_TYPE | null>((resolve, rejects) => {
				fs.readFile(this.PathGenrator(path), { encoding: 'utf-8' }, (err, data) => {
					if (err) {
						rejects(err);
						return;
					}
					try {
						this.ConfigGenrator(path, JSON.parse(data)).then(data => {
							resolve(data);
						});
					} catch (error) {
						rejects(error);
					}
				});

			});
		}

		private async ConfigGenrator(output: string, cfg: RESOURCE_TYPE): Promise<tools.GENRATOR_CFG_TYPE | null> {
			if (!cfg.groups || !cfg.resources) {
				console.warn(`File: ${output}: Wrong file Format and this one will be skipped`);
				return null;
			}
			let tmplate: tools.GENRATOR_CFG_TYPE = { ...TMPLATE }; //配置文件
			tmplate.include = []; //清理一下……
			tmplate.exclude = [];
			delete tmplate.rename;
			tmplate.outputdir = output;
			tmplate.name = output;
			tmplate.res_path = tools.QueryEgretProperties(this.curRoot)?.path || tools.DEF_RES_PATH;
			tmplate.group_cfg += output.replace(/[.]/g, '_');

			let tmpNameDic: { [name: string]: tools.RES_TYPE } = {};
			let tmpPathDic: { [url: string]: tools.RES_TYPE[] } = {};

			let url: string;
			for (let res of cfg.resources) {
				url = res.url;
				if (!url) {
					console.warn(`File: ${output}: ResName: ${res.name}'s path is null skip`);
					continue;
				}

				if (!tmpPathDic[url]) {
					tmpPathDic[url] = [];
				}
				if ("sheet" == res.type || "font" == res.type) { //需要特殊处理的对象
					try {
						let picPath = res.url.split('');
						let sheetFile = JSON.parse(fs.readFileSync(this.PathGenrator(res.url), { encoding: 'utf-8' }).replace(/^\uFEFF/, ''));
						picPath.splice(picPath.lastIndexOf('/'), picPath.length - picPath.lastIndexOf('/'), `/${sheetFile.file}`);
						res.picUrl = picPath.join('');
					} catch (e) {
						console.error(`Res Check Error, Path: ${res.url}`);
						console.error(e);
					}

				}
				tmpPathDic[url].push(res);
			}


			let tmp: string[];
			let fileName: string;
			let fileResName: string;
			let subFix: string;
			for (url in tmpPathDic) {
				tmp = url.split('/');
				fileName = tmp[tmp.length - 1];
				subFix = fileName.substring(fileName.lastIndexOf('.') + 1);
				fileResName = fileName.replace(RegExp(`.(?=${subFix}$)`), '_');
				if (tmpPathDic[url].length > 1 || tmpPathDic[url][0].name != fileResName) { //存在两个
					if (!tmplate.rename) {
						tmplate.rename = {};
					}
					tmplate.rename[tmpPathDic[url][0].url] = [];
					for (let res of tmpPathDic[url]) {
						tmplate.rename[res.url].push(res.name);
						tmpNameDic[res.name] = res;
					}
				} else {
					tmpNameDic[tmpPathDic[url][0].name] = tmpPathDic[url][0];
				}
				if ("sheet" == tmpPathDic[url][0].type || "font" == tmpPathDic[url][0].type) {
					tmpPathDic[url][0].picUrl && tmplate.include.push(tmpPathDic[url][0].picUrl!);
				}
				tmplate.include.push(tmpPathDic[url][0].url); //至少有一个……
			}

			await this.GroupGenrator(tmplate, tmpNameDic, cfg);

			return tmplate;
		}

		private async GroupGenrator(gourpCfg: tools.GENRATOR_CFG_TYPE, tmpNameDic: { [name: string]: tools.RES_TYPE }, cfg: RESOURCE_TYPE) {

			let path: string = `${this.CfgPath}/${gourpCfg.group_cfg}`;
			let names: string[];
			let template: string[];

			tools.CreateFolder(path, true);

			for (let group of cfg.groups) {
				names = group.keys.split(',');
				template = [];
				for (let name of names) {
					if (tmpNameDic[name] && tmpNameDic[name].url) {
						template.push(tmpNameDic[name].url);
						if ("sheet" == tmpNameDic[name].type || "font" == tmpNameDic[name].type) {
							tmpNameDic[name].picUrl && template.push(tmpNameDic[name].picUrl!);
						}
					} else {
						console.warn(`File: ${gourpCfg.outputdir}: Wrong resource config, GroupName: ${group.name}, ResourceName: ${name}`);
					}
				}

				let formatedData = this.formater.CheckFiles(template || [], true);

				let tmpData: tools.GROUP_CFG_TYPE = {
					include: formatedData.include,
					exclude: formatedData.exclude
				}

				fs.writeFileSync(`${path}/${group.name}.json`, JSON.stringify(tmpData, null, 4), {
					encoding: 'utf-8'
				});
			}
		}

		private get CfgPath(): string {
			return `${this.curRoot}/${this.generalCfg.cfg_path}`;
		}

		private get ResPath(): string {
			return `${this.curRoot}/${tools.QueryEgretProperties(this.curRoot)?.path || tools.DEF_RES_PATH}`;
		}

		private PathGenrator(tmpPath: string): string {
			return `${this.ResPath}/${tmpPath}`;
		}

		private curRoot: string;
		private generalCfg: tools.GENERAL_CFG_TYPE;

		// private formater: format_genrator.CfgFormat;
		private formater: res_format.ResCheck;
	}
}